import java.awt.Color;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Properties;


public class ClientController {

	static Player localPlayer;
	static Properties config;
	static GUI_Main_Menu guigmm;

	private GameBoard gb;
	private GameLogic gl;
	private Protocol proto;
	private GUI_Game_Board guigb;
	
	public ClientController(){
	}

	public static void readConfig(String [] args){
		//load configuration file

		config = new Properties();
		try {
			config.load(new FileInputStream(args[0]));
		} catch (Exception e1) {
			System.err.println("failed to load configuration file: " + e1.getMessage());
			System.exit(1);
		}

		//read values off config file, and set up accordingly
		String name = config.getProperty("name");
		int colorRGB = Integer.parseInt(config.getProperty("color"));
		localPlayer = new Player(name, new Color(colorRGB));		
	}

	public static void startGUI(){
		//start the gui
		guigmm = new GUI_Main_Menu();
	}

	public boolean connect(String ipAddress, int port){
		gb = new GameBoard(8,6);
		gl = new GameLogic();
		Socket conn = null;
		proto = null;
		try
		{
			InetAddress addr = InetAddress.getByName(ipAddress);
			
			conn = new Socket(addr, port);
			proto = new Protocol(conn, gl, gb);
		} catch (Exception e) {
			return false;
		}
		
		//enter net recieve loop
		int[] dim = null;
		try
		{
			dim = proto.getBoardSize();

			gb.setXDimension(dim[0]);
			gb.setYDimension(dim[1]);
			guigb = new GUI_Game_Board(gb,gl, proto);
			ArrayList<Player> plist = proto.getPlayers();
			if(proto.getStatus() == 1)
			{
				while(proto.readProtoMessage())
				{
					if(proto.last.equals(Protocol.MESSAGE_TYPES.RESET))
						break;
				}
			}
			for(Iterator<Player> it = plist.iterator(); it.hasNext();)
			{
				Player p = it.next();
				gl.addPlayer(p);
				guigb.addPlayer(p.getUserName(), p.getColor());
			}
			
			proto.sendPlayer(localPlayer);
			guigb.addPlayer(localPlayer.getUserName(), localPlayer.getColor());
			//we are not the first player, give them the turn marker
			if(gl.playerList.size() > 0)
				guigb.getPlayerFromList(gl.playerList.get(0).getUserName()).giveTurn();
			else
				guigb.getPlayerFromList(localPlayer.getUserName()).giveTurn();
			guigb.setNumPlayers(gl.playerList.size() + 1);
		}
		catch(Exception e)
		{
			return false;
		}
		return true;
	}
	
	public void run(){
		new ClientThread().start();
	}

	private class ClientThread extends Thread {
		
		ClientThread(){
		}
		public void run()
		{
			while(proto.readProtoMessage())
			{
				GamePiece p = null;
				if(proto.last.equals(Protocol.MESSAGE_TYPES.MOVE) && (p = proto.getPiece()) != null)
				{
					if(guigb.isReady()){
						p.setColor(gl.getTurn().getColor());
						guigb.move(p);
					}else{
						gb.reset();
					}
				}
				else if(proto.last.equals(Protocol.MESSAGE_TYPES.PLAYER_INFO) && proto.getPlayerCount() > gl.playerList.size())
				{
					gl.addPlayer(proto.getPlayer());
					guigb.addPlayer(proto.getPlayer().getUserName(), proto.getPlayer().getColor());
					guigb.setNumPlayers(gl.playerList.size());
				}
				else if(proto.last.equals(Protocol.MESSAGE_TYPES.TURN_ROTATE))
				{
					guigb.getPlayerFromList(gl.getTurn().getUserName()).removeTurn();
					gl.nextTurn();
					guigb.getPlayerFromList(gl.getTurn().getUserName()).giveTurn();
				}
				else if(proto.last.equals(Protocol.MESSAGE_TYPES.WON))
				{
					guigb.addChatMessage("Player " + gl.playerList.get(proto.getWinner()).getUserName() + " won the game\n");
				}
				else if(proto.last.equals(Protocol.MESSAGE_TYPES.STALEMATE))
				{
					guigb.addChatMessage("Stalemate!\n");
				}
				else if(proto.last.equals(Protocol.MESSAGE_TYPES.RESET))
				{
					guigb.reset();	
				}
				else if(proto.last.equals(Protocol.MESSAGE_TYPES.CHAT))
				{
					guigb.addChatMessage(proto.getChat());
				}
				else if(proto.last.equals(Protocol.MESSAGE_TYPES.READY))
				{
					guigb.incrementReady();
				}
				else if(proto.last.equals(Protocol.MESSAGE_TYPES.DISCONNECT))
				{
					guigb.removePlayer(gl.playerList.get(proto.getDisconnect()).getUserName());
					gl.removePlayer(proto.getDisconnect());
					guigb.setNumPlayers(gl.playerList.size());
					guigb.decrementReady();//this works most of the time, and i wouldn't consider it too serious in the cases where it doesn't
				}
			}
		}
	}

	//Entry point for the application
	public static void main(String[] args) {
		readConfig(args);
		startGUI();

	}
}
